﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Web.Mvc;
using Quizz.Infrastructure;
using Quizz.Infrastructure.Common;
using Quizz.Infrastructure.Models;
using Quizz.Library.Common;
using Quizz.Library.Helper;
using Quizz.Library.QuizzServiceReference;
using Quizz.Library.Security;
using System.Drawing.Drawing2D;
using System.Drawing;
using System.IO;
using System.Drawing.Imaging;
using Quizz.Infrastructure.Models;
using Quizz.Library.Filter;

namespace Quizz.Library.Actions
{
    public class AccountAction : BasicAction
    {
        public AccountAction(System.Web.Mvc.Controller controller)
            : base(controller)
        {

        }

        public FileContentResult Captcha(){
            var randomText = GenerateRandomText(6).ToLower();
            var hash = Hash.GetHash(randomText + GetSalt(), Hash.HashType.MD5);
            Session["CaptchaHash"] = hash;

            var rnd = new Random();
            var fonts = new[] { "Verdana", "Times New Roman", "Arial", "Comic Sans MS" };
            float orientationAngle = rnd.Next(0, 359);
            const int height = 35;
            const int width = 100;
            var index0 = rnd.Next(0, fonts.Length);
            var familyName = fonts[index0];

            using (var bmpOut = new Bitmap(width, height))
            {
                var g = Graphics.FromImage(bmpOut);
                var gradientBrush = new LinearGradientBrush(new Rectangle(0, 0, width, height),
                                                            Color.Green, Color.DarkGray,
                                                            orientationAngle);
                g.FillRectangle(gradientBrush, 0, 0, width, height);
                g.DrawString(randomText, new Font(familyName, 18), new SolidBrush(Color.Wheat), 0, 2);
                DrawRandomLines(ref g, width, height);
                var ms = new MemoryStream();
                bmpOut.Save(ms, ImageFormat.Png);
                var bmpBytes = ms.GetBuffer();
                bmpOut.Dispose();
                ms.Close();

                return new FileContentResult(bmpBytes, "image/png");
            }
        }

        public JsonResult RequestPassword(string email, string captcha)
        {
            if(!ValidateCaptcha(captcha))
            {
                return CommonMethods.CreateJson(new {result = false, message = "Chuỗi xác thực không đúng."}, false);
            }

            using (var proxy = new QuizzProjectServiceClient())
            {
                var user = proxy.UserGetByEmail(email);
                if(user == null)
                {
                    return CommonMethods.CreateJson(
                        new {result = false, message = "Không có tài khoản nào trùng khớp."}, false);
                }
                var newPassword = (new RandomPasswordGenerator {MinimumLength = 8, MaximumLength = 12}).Create();
                var hash = Hash.GetHash(newPassword, Hash.HashType.SHA256);
                user.Password = hash;
                try
                {
                    MailHelper.SendNewPassEmail(user, newPassword);
                    proxy.UserUpdate(user);
                } catch
                {
                    return
                        CommonMethods.CreateJson(new {result = false, message = "Có lỗi trong khi cập nhật mật khẩu."}, false);
                }

                return CommonMethods.CreateJson(new {result = true}, false);
            }
        }

        public JsonResult Register(User user, string captcha)
        {
            // Validate user
            var validateResult = ValidateRegisterInfo(user, captcha);
            if(validateResult.HasError())
            {
                return CommonMethods.CreateJson(new {result = false, message = validateResult.ToString("<br />")}, false);
            }

            user.RoleId = Constants.USER_ROLE_ID;
            user.IsDeleted = false;
            user.IsLocked = false;
            user.RegisterDate = DateTime.Now;
            user.Status = (int) UserStatus.Activated;
            user.Avartar = string.Empty;

            // Save user
            using(var proxy = new QuizzProjectServiceClient())
            {
                try
                {
                    proxy.UserInsert(user);
                    MailHelper.SendRegisterEmail(user);
                } catch (Exception ex)
                {
                    return CommonMethods.CreateJson(new {result = false, message = ex.Message}, false);
                }
            }

            return CommonMethods.CreateJson(new {result = true}, false);
        }

        public JsonResult ChangePassword(string oldPass, string newPass)
        {
            using (var proxy = new QuizzProjectServiceClient())
            {
                var user = proxy.UserGetById(AccessFactory.CurrentUser.Id);
                var errors = new ErrorReportResult();
                if (!user.Password.Equals(oldPass, StringComparison.OrdinalIgnoreCase))
                {
                    errors.AddError("Mật khẩu cũ không khớp");
                }
                if (errors.HasError())
                {
                    return CommonMethods.CreateJson(new {result = false, message = errors.ToString("<br />")}, false);
                }
                user.Password = newPass;
                proxy.UserUpdate(user);
                MailHelper.SendChangeProfile(user);
            }

            return CommonMethods.CreateJson(new {result = true}, false);
        }

        public JsonResult ChangeProfile(User user)
        {
            using (var proxy = new QuizzProjectServiceClient())
            {
                var oldUser = proxy.UserGetById(AccessFactory.CurrentUser.Id);
                oldUser.FirstName = user.FirstName;
                oldUser.LastName = user.LastName;
                oldUser.Phone = user.Phone;
                oldUser.Address = user.Address;
                proxy.UserUpdate(oldUser);
                MailHelper.SendChangeProfile(oldUser);
                AccessFactory.CurrentUser = oldUser;
            }
            return CommonMethods.CreateJson(new {result = true}, false);
        }

        #region Private Methods

        private static void DrawRandomLines(ref Graphics g, int width, int height)
        {
            var rnd = new Random();
            for (var i = 0; i < 10; i++)
            {
                var pen = new Pen(Color.DarkTurquoise);
                g.DrawLine(pen, rnd.Next(0, width), rnd.Next(0, height),
                                rnd.Next(0, width), rnd.Next(0, height));
            }
        }

        private static string GetSalt()
        {
            return typeof(AccountAction).Assembly.FullName;
        }

        private static string GenerateRandomText(int textLength)
        {
            const string chars = "ABCDEFGHIJKLMNPQRSTUVWXYZ23456789abcdefghklmnpqrstuvw";
            var random = new Random();
            var result = new string(Enumerable.Repeat(chars, textLength)
                  .Select(s => s[random.Next(s.Length)]).ToArray());
            return result;
        }

        private bool ValidateCaptcha(string captchaValue)
        {
            var expectedHash = Session["CaptchaHash"];
            if (expectedHash == null)
                return false;
            var toCheck = captchaValue.ToLower() + GetSalt();
            var hash = Hash.GetHash(toCheck, Hash.HashType.MD5);
            return hash.Equals(expectedHash);
        }

        public ErrorReportResult ValidateRegisterInfo(User user, string captcha)
        {
            var validateResults = new ErrorReportResult();

            if (!ValidateCaptcha(captcha))
            {
                validateResults.AddError("Mã xác thực không đúng.");
            }

            if (!CommonValidate.IsEmail(user.Email))
            {
                validateResults.AddError("Email không hợp lệ.");
            } else
            {
                using (var proxy = new QuizzProjectServiceClient())
                {
                    if (!proxy.UserIsEmailAvailable(user.Email))
                    {
                        validateResults.AddError("Email đã được sử dụng.");
                    }
                }
            }

            if (user.FirstName.Length < 3)
            {
                validateResults.AddError("Họ quá ngắn");
            }

            if (user.LastName.Length < 3)
            {
                validateResults.AddError("Tên quá ngắn");
            }

            if (!CommonValidate.IsPhoneNumber(user.Phone))
            {
                validateResults.AddError("Số điện thoại không hợp lệ.");
            }

            return validateResults;
        }

        #endregion
    }
}
